package com.pmcc.utils.wechat;

import org.apache.commons.codec.digest.DigestUtils;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @program: basePlatform
 * @description: 微信支付
 * @author: Mr.Xue
 * @create: 2020-03-25 15:22
 **/
public class WechatUtil {

    public static String paySign(Object payBean, String appKey) {
        String[] a = toParamArray(payBean, "sign");
        return paySign(a, appKey);
    }

    private static String[] toParamArray(Object bean, String... excludeField) {
        Field[] fa = bean.getClass().getDeclaredFields();
        List<String> list = new ArrayList<String>();
        Set<String> excludeSet = new HashSet<String>(
                Arrays.asList(excludeField));
        for (Field f : fa) {
            try {
                String name = f.getName();
                f.setAccessible(true);
                Object v = f.get(bean);
                boolean valid = false;
                if (v != null) {
                    if (v instanceof String) {
                        String sv = (String) v;
                        if (!isEmpty(sv)) {
                            valid = true;
                        }
                    } else {
                        valid = true;
                    }
                }
                if (valid) {
                    if (!excludeSet.contains(name)) {
                        String kv = name + "=" + v.toString();
                        list.add(kv);
                    }
                }
            } catch (IllegalArgumentException ex) {
                Logger.getLogger(WechatUtil.class.getName()).log(Level.SEVERE,
                        null, ex);
            } catch (IllegalAccessException ex) {
                Logger.getLogger(WechatUtil.class.getName()).log(Level.SEVERE,
                        null, ex);
            }
        }
        return list.toArray(new String[list.size()]);
    }

    //根据map生成签名
    public static String paySignByMap(Map<String, Object> map, String appKey) {
        List<String> list = new ArrayList<>();
        for (Map.Entry<String, Object> e : map.entrySet()) {
            String key = e.getKey();
            Object v = e.getValue();
            String kv = key + "=" + v.toString();
            list.add(kv);
        }
        return paySign(list.toArray(new String[list.size()]), appKey);
    }

    public static String paySign(String[] a, String appKey) {
        String stringA = buildSignString(a);
        String stringSignTemp = stringA + "&key=" + appKey;
        // System.out.println("stringSignTemp="+stringSignTemp);
        String md5 = DigestUtils.md5Hex(stringSignTemp).toUpperCase();
        return md5;
    }

    public static String buildSignString(String[] a) {
        Arrays.sort(a);
        // String s = ObjectUtils.concat(a);
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (String e : a) {
            if (first) {
                first = false;
            } else {
                sb.append("&");
            }
            sb.append(e);
        }
        return sb.toString();
    }

    public static boolean isEmpty(String s) {
        return s == null || s.length() == 0;
    }

    /**
     * 微信将xml转换成实体
     *
     * @param xml
     * @param type
     * @return
     * @throws JAXBException
     */
    public static Object fromXml(String xml, Class type) throws JAXBException {
        JAXBContext jc = JAXBContext.newInstance(type);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        return unmarshaller.unmarshal(new StringReader(xml));
    }


    /**
     * 微信将String类型转换成xml
     *
     * @param o
     * @return
     * @throws Exception
     */
    public static String toXml(Object o) throws Exception {
        StringWriter writer = new StringWriter();
        JAXBContext jc = JAXBContext.newInstance(o.getClass());
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(o, writer);
        return writer.toString();
    }
}
